package be.destin.abdera;

import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.apache.abdera.factory.Factory;
import org.apache.abdera.i18n.iri.IRI;
import org.apache.abdera.model.Content;
import org.apache.abdera.model.Entry;
import org.apache.abdera.model.Feed;
import org.apache.abdera.model.Person;
import org.apache.abdera.model.Text;
import org.apache.abdera.protocol.server.RequestContext;
import org.apache.abdera.protocol.server.RequestContext.Scope;
import org.apache.abdera.protocol.server.ResponseContext;
import org.apache.abdera.protocol.server.TargetType;
import org.apache.abdera.protocol.server.context.ResponseContextException;
import org.apache.abdera.util.Constants;
import org.apache.log4j.Logger;

import be.destin.beans.Reflector;
import be.destin.memo.Log;
import be.destin.memo.TagDef;
import be.destin.memo.Tagged;
import be.destin.memolog.UsageCount;
import be.destin.memolog.UsageLogger;
import be.destin.memolog.UsageMode;
import be.destin.skos.core.Application;
import be.destin.skos.core.Concept;
import be.destin.skos.core.ConceptIdentifier;
import be.destin.skos.core.ConceptScheme;
import be.destin.skos.core.Count;
import be.destin.skos.core.NoScheme;
import be.destin.skos.core.ReferringApplication;
import be.destin.skos.core.SchemeInterface;
import be.destin.skos.core.SchemeUsage;
import be.destin.skos.core.SkosManager;
import be.destin.skos.html.SkosHtmlManager;
import be.destin.util.Util;

public class MemoCollectionAdapter extends
		AbstractCorrectedCollectionAdapter<UsageLogger> {

/*
  void 	deleteEntry(String resourceName, RequestContext request)
          Delete an entry
 String 	getAuthor(RequestContext request)
          The author of this collection.
 List<Person> 	getAuthors(Employee entry, RequestContext request)
          Get the authors for an entry.
 Object 	getContent(Employee entry, RequestContext request)
          Get the content for the entry.
 Iterable<Employee> 	getEntries(RequestContext request)
          Get the listing of entries requested
 Employee 	getEntry(String resourceName, RequestContext request)
          Get a specific entry
 String 	getId(Employee entry)
          Gets the UUID for the specified entry.
 String 	getId(RequestContext request)
          A unique ID for this feed.
 String 	getName(Employee entry)
          Get the name of the entry resource (used to construct links)
 String 	getTitle(Employee entry)
          Get the title fo the entry
 String 	getTitle(RequestContext request)
          The title of our collection.
 Date 	getUpdated(Employee entry)
          Get the value to use in the atom:updated element
 Employee 	postEntry(String title, IRI id, String summary, Date updated, List<Person> authors, Content content, RequestContext request)
          Create a new entry
 void 	putEntry(Employee employee, String title, Date updated, List<Person> authors, String summary, Content content, RequestContext request)
          Update an entry.

 */
	
	/** log4j category */
	private static Logger log = Logger.getLogger(MemoCollectionAdapter.class);

	Concept criteria = null;
	UsageMode baseMode = null; // null means synthesis of all modes...
	SkosManager skosManager = null;

	/**
	 * @param skosManager to access SKOS schemes
	 * @param criteria: application or user
	 * @param mode: display, read, update, comment, tagdef, tagged...
	 */
	public MemoCollectionAdapter(SkosManager skosManager, Concept criteria, UsageMode mode) {
		super();
		this.skosManager = skosManager;
		this.criteria = criteria;
		this.baseMode = mode;
		this.setHref(/*Now is a different Workspace: mode.toString()+SchemeInterface.separator+*/
					criteria.getAbout()); // and not Scheme_About if users would be collections like applications...
	}

	public String getTitle(String language, String application, String record) {
		Concept aConcept = null;
		if (application != null && record != null) {
			if (SkosHtmlManager.askosiDisplayApplication.equalsIgnoreCase(application)) {
				aConcept = skosManager.getScheme_Concept(record);
			} else {
				Concept currApp = skosManager.getApplications().getConcept(application);
				if (currApp instanceof Application) {
					aConcept = ((Application)currApp).getDerivedConcept(record);
				}
			}
		}
		if (aConcept != null) {
			return aConcept.getPrefLabel(language, false);
		}
		return (application+" / "+record);
	}
	
	@Override
	public String getTitle(RequestContext context) {
		String language = ConceptCollectionAdapter.getUserLanguage(context);
		return (baseMode != null ? (baseMode.getNiceName()+" : "):"")+criteria.getPrefLabel(language, false);
	}

    public ResponseContext getPropertyFeed(RequestContext request, UsageLogger entity, String navigationProperty) {
        try {
    		Factory factory = request.getAbdera().getFactory();
    		Feed feed = factory.newFeed();
    		feed.setId(getId(request)+'('+getResourceName(request)+')'+navigationProperty);
    		feed.setTitle(getTitle(request)+" ("+getResourceName(request)+") "+navigationProperty);
    		feed.addAuthor(getAuthor(request));
    		feed.setUpdated(new Date());

            addPropertyFeedDetails(feed, request, entity, navigationProperty);

            return buildGetFeedResponse(feed);
        } catch (ResponseContextException e) {
            return createErrorResponse(e);
        }
    }

    public ResponseContext getEntriesListFeed(RequestContext request, String entriesList) {
        try {
    		Factory factory = request.getAbdera().getFactory();
    		Feed feed = factory.newFeed();
    		feed.setId(getId(request)+'('+entriesList+')');
    		feed.setTitle(getTitle(request)+" ("+entriesList+")");
    		feed.addAuthor(getAuthor(request));
    		feed.setUpdated(new Date());

            addEntriesListDetails(feed, request, entriesList);

            return buildGetFeedResponse(feed);
        } catch (ResponseContextException e) {
            return createErrorResponse(e);
        }
    }
	
	
	@Override
	public void deleteEntry(String about, RequestContext context)
			throws ResponseContextException {
			if (baseMode == null) throw new ResponseContextException("Don't know how to delete all usage modes for "+about,501);
			if (criteria.getInScheme() != skosManager.getApplications()) throw new ResponseContextException("Must delete from an application and not from a user: "+criteria.getScheme_About()+", record="+about,501);
			UsageLogger usageLogger = MemoProvider.getNewUsageLogger(context,this.criteria.getAbout(),about,this.baseMode);
			usageLogger.delete();
	}

	@Override
	public List<UsageLogger> getListEntries(RequestContext context)
			throws ResponseContextException {
		UsageLogger usageLogger = MemoProvider.getNewUsageLogger(context,this.criteria.getAbout(),null,this.baseMode);
		return usageLogger.listUsage();
	}

	@Override
	public UsageLogger getEntry(String about, RequestContext context)
			throws ResponseContextException {
		return MemoProvider.getNewUsageLogger(context,this.criteria.getAbout(),about,this.baseMode);
	}
	
    /**
     * Add the details to an entry
     * 
     * @param request The request context
     * @param e The entry
     * @param feedIri The feed IRI
     * @param entryObj
     */
	@Override
    protected String addEntryDetails(RequestContext request, Entry e, IRI feedIri, UsageLogger anUsage)
        throws ResponseContextException {
		/*
		 *       (atomAuthor*
		 *        &amp; atomCategory*
		 *        &amp; atomContent?
		 *        &amp; atomContributor*
		 *        &amp; atomId
		 *        &amp; atomLink*
		 *        &amp; atomPublished?
		 *        &amp; atomRights?
		 *        &amp; atomSource?
		 *        &amp; atomSummary?
		 *        &amp; atomTitle
		 *        &amp; atomUpdated
		 *        &amp; extensionElement*)
		 */
		String language = getUserLanguage(request);

		HashMap<String,String> param = new HashMap<String,String>();
		param.put("collection", anUsage.getApplication());
		param.put("entry", anUsage.getRecord());
		String link = request.urlFor(TargetType.TYPE_ENTRY, param);
		UsageMode entriesMode = (UsageMode)request.getAttribute(Scope.REQUEST, "entriesMode");
		if (entriesMode != null && entriesMode != baseMode) {
			link = link.replaceFirst( baseMode.name().toLowerCase(), entriesMode.name().toLowerCase());
		}
		//String link = MemoProvider.memoWorkspaces[this.entriesMode.ordinal()].urlFor(request,TargetType.TYPE_ENTRY, param);

		if (link!=null && !link.isEmpty()) {
			e.addLink(link, "self");
/* duplicated code because of bad link generation */
			e.addLink(link, "edit");
		}
		e.setId(link);

		UsageCount total = anUsage.count();
		String title = getTitle(language, anUsage.getApplication(), anUsage.getRecord());
		String totalDisplayed = total.toString();
		if ("1".equals(totalDisplayed)) totalDisplayed = "";
		e.setTitle( title + " : "+ totalDisplayed + ' ' + anUsage.getMode().getNiceName() );

		Date date = total.getMaxDate();
		if (date.getTime() < Long.MAX_VALUE && date.getTime() > 0) e.setUpdated(date);
		date = total.getMinDate();
		if (date.getTime() > 0) e.setPublished(date);

		List<Person> authors = getAuthors(anUsage, request);
		if (authors != null) {
			for (Person a : authors) {
				e.addAuthor(a);
			}
		}

		if (anUsage.getMode() == UsageMode.TAGGED) {
			Log[] currentTags = anUsage.getLoggerRec();
			for (Log oneEntry : currentTags) {
				if (oneEntry instanceof Tagged) {
					TagDef tagRec = ((Tagged)oneEntry).getTaghead();
					e.addCategory(tagRec.getAppli(), tagRec.getRecord(), getTitle(language,tagRec.getAppli(), tagRec.getRecord()));
				}
			}
		} else if (anUsage.getMode() == UsageMode.TAGDEF) { // count tagged records and create a $link/tagged to them
			if (link!=null && !link.isEmpty()) {
				Log[] logs = anUsage.getLoggerRec();
				e.addLink(link+"/$links/tagged", "scheme:tagged", Constants.FEED_MEDIA_TYPE,""+logs.length,language,-1);
			}
		}


/*
		String rights = aConcept.getInScheme().getRights(language);
		if (rights != null && !rights.isEmpty()) {
			e.setRights(rights);
		}

		Text t = getSummary(aConcept, request);
		if (t != null) {
			e.setSummaryElement(t);
		}
*/
		/* end of duplicated code because of bad link generation */

		/* TODO: categories = tag for the entry */
		//e.addCategory(scheme.getAbout(), anAbout, aLabel);

		/**
		 * Add a link to the entry
		 * 
		 * @param href The IRI of the link
		 * @param rel The link rel attribute
		 * @param type The media type of the link
		 * @param hreflang The language of the target
		 * @param length The length of the resource
		 * @return The newly created atom:link
		 * @throws IRISyntaxException if the href is malformed
		    Link addLink(String href, String rel, String type, String title, String hreflang, long length);
		 */
/* rel: This document defines five initial values for the Registry of Link
   Relations:

   1.  The value "alternate" signifies that the IRI in the value of the
       href attribute identifies an alternate version of the resource
       described by the containing element.

   2.  The value "related" signifies that the IRI in the value of the
       href attribute identifies a resource related to the resource
       described by the containing element.  For example, the feed for a
       site that discusses the performance of the search engine at
       "http://search.example.com" might contain, as a child of
       atom:feed:

       <link rel="related" href="http://search.example.com/"/>

       An identical link might appear as a child of any atom:entry whose
       content contains a discussion of that same search engine.

   3.  The value "self" signifies that the IRI in the value of the href
       attribute identifies a resource equivalent to the containing
       element.

   4.  The value "enclosure" signifies that the IRI in the value of the
       href attribute identifies a related resource that is potentially
       large in size and might require special handling.  For atom:link
       elements with rel="enclosure", the length attribute SHOULD be
       provided.

   5.  The value "via" signifies that the IRI in the value of the href
       attribute identifies a resource that is the source of the
       information provided in the containing element.
 */
		if (anUsage.getApplication() != null) {
			SkosHtmlManager skosHtmlManager = this.getSkosHtmlManager(request);
			Concept currApp = skosManager.getApplications().getConcept(anUsage.getApplication());
			if (currApp instanceof Application) {
				String anIcon = null;
				Application anApp = (Application)currApp;
				if (anApp.getDisplayURL() != null) {
					String display = anApp.getDisplayURL(anUsage.getRecord()); 
					if (display != null && !display.isEmpty()) e.addLink(display, "alternate");
				}
				if (anApp.getPreviewURL() != null) {
					String preview = anApp.getPreviewURL(anUsage.getRecord()); 
					if (preview != null && !preview.isEmpty()) e.addLink(preview, "preview");
				}
				Concept aConcept = null;
				if (SkosHtmlManager.askosiDisplayApplication.equalsIgnoreCase(anUsage.getApplication())) {
					aConcept = skosManager.getScheme_Concept(anUsage.getRecord());
				} else {
					aConcept = anApp.getDerivedConcept(anUsage.getRecord());
				}
				if (aConcept != null) {
					ConceptScheme aScheme = aConcept.getInScheme();
					String rights = aConcept.getInScheme().getRights(language);
					if (rights != null && !rights.isEmpty()) {
						e.setRights(rights);
					}

					String aNote = aConcept.getScopeNote(language);
					if (aNote != null && !aNote.isEmpty()) {
						Text t = request.getAbdera().getFactory().newSummary(Text.Type.TEXT);
						if (t != null) {
							t.setText(aNote);
							e.setSummaryElement(t);
						}
					}

					if (aScheme != null && aConcept.getBroader() != null) {
						for (String anAbout : aConcept.getScheme_AboutBroaderTransitive()) {
							Concept btConcept = skosManager.getScheme_Concept(anAbout,aScheme, null, null);
							if (btConcept != null) {
								String aLabel = btConcept.getPrefLabel(language, false);
								if (aLabel == null || aLabel.isEmpty()) {
									aLabel = anAbout;
								}
								e.addCategory(aScheme.getAbout(), anAbout, aLabel);
							}
						}
					}
					String askosiRoot = skosHtmlManager.getApplicationRoot(SkosHtmlManager.askosiDisplayApplication);

					if (aScheme == skosManager.getMetaScheme()) {
						SchemeInterface refScheme = skosManager.openScheme(aConcept.getAbout());
						if (refScheme instanceof NoScheme && (refScheme.getClass() != NoScheme.class)) {
							Collection<ConceptIdentifier> tops = refScheme.getHasTopConcept();			
							param.put("collection", refScheme.getAbout());
							for (ConceptIdentifier anAbout : tops) {
								param.put("entry", anAbout.getAbout());
								String toplink = request.urlFor(TargetType.TYPE_ENTRY, param);
								e.addLink(toplink, "section");
							}
						}
					}

					if (askosiRoot!=null && !askosiRoot.isEmpty()) {
						e.addLink(Util.noMoreSubstitute(Reflector.substituteURL(askosiRoot, aConcept, SkosHtmlManager.askosiDisplayUrl, language)), "alternate");
					}
					String aUrl = aConcept.getUrlAdapted(skosHtmlManager);
					if (aUrl!=null && !aUrl.isEmpty()) {
						e.addLink(Util.noMoreSubstitute(aUrl), "via");
					}
					anIcon = aConcept.getIconAdapted(skosHtmlManager);
					if (anIcon==null || anIcon.isEmpty()) {
						anIcon = aConcept.getInScheme().getIconAdapted(skosHtmlManager);
					}
					Object[] params = new Object[2];
					params[0] = aConcept;
					for (ReferringApplication appl : aConcept.getUsage()) {
						String applUsed = appl.getApplication();
						for (Count use : appl.getCount()) {
							String aRole = use.getRole();
							if (aRole == null) continue;
							SchemeUsage schemeUsage = aConcept.getInScheme().getApplicationUsage(applUsed,aRole);
							if (schemeUsage == null) continue;
							params[1] = use;
							aUrl = schemeUsage.getSearchURL();
							if (aUrl != null && !aUrl.isEmpty()) {
								e.addLink(Util.noMoreSubstitute(Reflector.substituteURL(askosiRoot, params, aUrl, language)),
										applUsed+':'+aRole, "text/html",""+use.getCount(),language,-1);
							}
							aUrl = schemeUsage.getAtomURL();
							if (aUrl != null && !aUrl.isEmpty()) {
								e.addLink(Util.noMoreSubstitute(Reflector.substituteURL(askosiRoot, params, aUrl, language)),
										applUsed+':'+aRole, Constants.FEED_MEDIA_TYPE,""+use.getCount(),language,-1);
							}
						}
					}
				}
				if (anIcon==null || anIcon.isEmpty()) {
					anIcon = anApp.getIconAdapted(skosHtmlManager);
				}
				if (anIcon!=null && !anIcon.isEmpty()) {
					e.addLink(Util.noMoreSubstitute(anIcon), "icon");
				}
			}
		}
/*
		SkosHtmlManager skosHtmlManager = this.getSkosHtmlManager(request);
		String appRoot = skosManager.getUrlRoots(anUsage.getApplication());
		if (appRoot!=null && !appRoot.isEmpty()) {
			e.addLink(skosManager.getApplications().getConcept(anUsage.getApplication()).getUrlAdapted(skosHtmlManager), "alternate");
		}
		Object[] params = new Object[2];
		params[0] = aConcept;
		for (ReferringApplication appl : aConcept.getUsage()) {
			String applUsed = appl.getApplication();
			for (Count use : appl.getCount()) {
				String aRole = use.getRole();
				if (aRole == null) continue;
				SchemeUsage schemeUsage = aConcept.getInScheme().getApplicationUsage(applUsed,aRole);
				if (schemeUsage == null) continue;
				params[1] = use;
				aUrl = schemeUsage.getSearchURL();
				if (aUrl != null && !aUrl.isEmpty()) {
					e.addLink(Util.noMoreSubstitute(Reflector.substituteURL(appRoot, params, aUrl, language)),
							  applUsed+':'+aRole, "text/html",""+use.getCount(),language,-1);
				}
				aUrl = schemeUsage.getAtomURL();
				if (aUrl != null && !aUrl.isEmpty()) {
					e.addLink(Util.noMoreSubstitute(Reflector.substituteURL(appRoot, params, aUrl, language)),
							  applUsed+':'+aRole, Constants.FEED_MEDIA_TYPE,""+use.getCount(),language,-1);
				}
			}
		}
*/
		return link;
    }

	@Override
	public String getId(UsageLogger anUsage) throws ResponseContextException {
		if (anUsage == null) return null;
		return anUsage.getUserApplicationRecord();
	}

	@Override
	public String getName(UsageLogger anUsage) throws ResponseContextException {
		if (anUsage == null) return null;
		return anUsage.getRecord();
	}

	@Override
	public String getTitle(UsageLogger anUsage) throws ResponseContextException {
		if (anUsage == null) return null;
		return getTitle(language, anUsage.getApplication(), anUsage.getRecord() + " : " + anUsage.getMode().getNiceName() );
	}

	@Override
	public Date getUpdated(UsageLogger anUsage) throws ResponseContextException {
		return anUsage.count().getMaxDate();
	}

/*
UsageLogger 	postEntry(String title, IRI id, String summary, Date updated, List<Person> authors, Content content, RequestContext request)
          Create a new entry
 * @see org.apache.abdera.protocol.server.impl.AbstractEntityCollectionAdapter#postEntry(java.lang.String, org.apache.abdera.i18n.iri.IRI, java.lang.String, java.util.Date, java.util.List, org.apache.abdera.model.Content, org.apache.abdera.protocol.server.RequestContext)
 */
	public UsageLogger postEntry(String title, IRI id, String summary, Date updated, List<Person> authors, Content content, RequestContext request) {
		UsageLogger anUsage = ((MemoProvider)request.getProvider()).getNewUsageLogger(request,id.getQuery(),this.baseMode);
		anUsage.start();
		anUsage.setInfoMessage(summary);
		anUsage.stop();
		return anUsage;
	}

	/*
	Update an entry.

	Parameters:
	    entry The entry to update
	    title The new title of the entry
	    updated The new value of atom:updated
	    authors To new listing of authors
	    summary The new summary
	    content The new content
	    request The request context
	    */
	@Override
	public void putEntry(UsageLogger anUsage, String title, Date updated,
			List<Person> authors, String summary, Content content, RequestContext context)
			throws ResponseContextException {
		anUsage.start();
		anUsage.setInfoMessage(summary);
		anUsage.stop();
	}

	@Override
	public String getAuthor(RequestContext context)
			throws ResponseContextException {
		return null;
	}
/*
	public List<Person> getAuthors(UsageLogger anUsage) {
		LinkedList<String> names = scheme.getCreator();
		LinkedList<Person> authors = new LinkedList<Person>();
		if (names != null) {
			for (String aName : names) {
				Person person = new PersonWrapper();
				person.setName(aName);
				authors.add(person);
			}
		}
		names = scheme.getContributor();
		return authors;
	}
*/
	public List<Person> getAuthors(UsageLogger anUsage, RequestContext context) throws ResponseContextException {
		  Person author = context.getAbdera().getFactory().newAuthor();
		  author.setName(anUsage.getUser());
		  return Arrays.asList(author);
	}

	@Override
	public Object getContent(UsageLogger entry, RequestContext context) {
	    return null;
	}

	/*
	 * Get the summary of the entry. By default this returns null.
	 */
	public Text getSummary(UsageLogger anUsage, RequestContext context) {
		return null;
	}


	@Override
	public String getIconUrl(RequestContext request) {
		SkosHtmlManager skosHtmlManager = this.getSkosHtmlManager(request);
		String aUrl = criteria.getIconAdapted(skosHtmlManager);
		return Util.noMoreSubstitute(aUrl);
	}


	@Override
	public List<UsageLogger> getPropertyEntries(RequestContext request,
			UsageLogger entity, String navigationProperty)
			throws ResponseContextException {
		int pSep = navigationProperty.indexOf(':');
		if (pSep < 0) {
			pSep = navigationProperty.indexOf('/');
			if (pSep < 0) {
				pSep = navigationProperty.indexOf('_');
			}
		}
		String application = SkosHtmlManager.askosiDisplayApplication;
		String role = navigationProperty;
		if (pSep > 0) {
			application = navigationProperty.substring(0,pSep);
			role = navigationProperty.substring(pSep+1);
		}

		LinkedList<UsageLogger> result = new LinkedList<UsageLogger>();
		if (application.equalsIgnoreCase(SkosHtmlManager.askosiDisplayApplication)) { // Local property ?
			//Predicate currProp = Predicate.find(entity, role);
			if (role.equalsIgnoreCase("tagged")) {
				if (baseMode == UsageMode.TAGDEF) {
					request.setAttribute("entriesMode", UsageMode.TAGGED);
					Log[] logs = entity.getLoggerRec();
					if (logs != null && logs.length > 0) {
						for (Log oneLog : logs) {
							for (Tagged aTagged : ((TagDef)oneLog).getTagged()) {
								result.add(new UsageLogger(entity,aTagged));								
							}
						}
					}
				}				
			} else if (role.equalsIgnoreCase("tagdef") || role.equalsIgnoreCase("taghead")) {
				if (baseMode == UsageMode.TAGGED) {
					request.setAttribute("entriesMode", UsageMode.TAGDEF);
					Log[] logs = entity.getLoggerRec();
					if (logs != null && logs.length > 0) {
						for (Log oneLog : logs) {
							TagDef aTagDef = ((Tagged)oneLog).getTaghead();
							if (aTagDef != null) result.add(new UsageLogger(entity,aTagDef));								
						}
					}
				}
			}
		} else { // other applications which returns CONCEPTS ???
			log.error("Is this application_role really returns ASKOSI Concepts. If yes, yet to be implemented! "+application+'_'+role);
		}
		return result;
	}


	@Override
	public List<UsageLogger> getCommaSeparatedEntriesList(
			RequestContext request, String entriesList) {
		StringTokenizer st = new StringTokenizer(entriesList,",; \t");
		TreeSet<String> sorter = new TreeSet<String>();
		while (st.hasMoreTokens()) {
			sorter.add(st.nextToken());
		}
		LinkedList<UsageLogger> result = new LinkedList<UsageLogger>();
		for (String oneAbout: sorter) {
			UsageLogger toAdd = MemoProvider.getNewUsageLogger(request, this.criteria.getAbout(),oneAbout, baseMode);
			if (toAdd == null) {
				log.error("UsageLogger "+oneAbout+" (from entries list) not found in "+toAdd.getUserApplicationRecord());
			} else {
				result.add(toAdd);
			}
		}
		return result;
	}

	public Concept getCriteria() {
		return criteria;
	}


	public void setCriteria(Concept criteria) {
		this.criteria = criteria;
	}

/*
public CategoriesInfo[]   getCategoriesInfo(RequestContext request)
public ResponseContext  getCategories(RequestContext request)
public ResponseContext  deleteMedia(RequestContext request) {
public ResponseContext  getMedia(RequestContext request) {
public ResponseContext  headMedia(RequestContext request) {
public ResponseContext  optionsMedia(RequestContext request) {
public ResponseContext  putMedia(RequestContext request) {
public ResponseContext  postMedia(RequestContext request) {
public ResponseContext  headEntry(RequestContext request) {
public ResponseContext  optionsEntry(RequestContext request) {
public abstract String  getAuthor(RequestContext request) throws ResponseContextException;
public abstract String  getId(RequestContext request);
public ResponseContext  extensionRequest(RequestContext request) {

	Update a media resource. By default this method is not allowed. Implementations must override this method to support media resource updates

	Parameters:
	    entryObj
	    contentType The mime-type of the media resource
	    slug The value of the Slug request header
	    inputStream An input stream providing access to the request payload
	    request The request context

	    public void putMedia(T entryObj, MimeType contentType, String slug, InputStream inputStream, RequestContext request)

Post a new media resource to the collection. By default, this method is not supported. Implementations must override this method to support posting media resources

Parameters:
    mimeType The mime-type of the resource
    slug The value of the Slug header
    inputStream An InputStream providing access to the request payload
    request The request context

    public T  postMedia(MimeType mimeType, String slug, InputStream inputStream, RequestContext request)

Delete a media resource. By default this method is not supported. Implementations must override this method to support deleting media resources
    public void  deleteMedia(String resourceName, RequestContext request)

Get the name of the media resource. By default this method is unsupported. Implementations must override.
    public String  getMediaName(T entry)
 
Get an input stream for the media resource. By default this method is unsupported. Implementations must override.
    public InputStream  [More ...] getMediaStream(T entry)

True if this entry is a media-link entry. By default this always returns false. Implementations must override to support media link entries
    public boolean  isMediaEntry(T entry)


*/

}
